#include "downloadmanager.h"
#include <QFile>
#include <QFileInfo>
#include <QSslError>

DownloadManager::DownloadManager() : QObject(NULL)
{
    connect(&manager, &QNetworkAccessManager::finished, this, &DownloadManager::download_finished);
}

void DownloadManager::set_path(const QString &path)
{
    this->m_path = path;
}

//下载进度
void DownloadManager::replay_progress(qint64 bytesReceived, qint64 bytesTotal)
{
    emit download_progress(p_reply->url(), bytesReceived, bytesTotal);
}

//添加一个下载任务
void DownloadManager::add_download(const QUrl &url)
{
    //已经在下载，添加到队列中，等待上一个下载完毕
    if (download_queue.isEmpty()) {
        download_queue.enqueue(url);
        download();
    } else {
        download_queue.enqueue(url);
    }
}

//下载文件
void DownloadManager::download()
{
    if (download_queue.isEmpty()) {
        return;
    }

    QUrl            url = download_queue.head();
    QNetworkRequest request(url);

    QSslConfiguration conf = request.sslConfiguration();
    conf.setPeerVerifyMode(QSslSocket::VerifyNone);
    conf.setProtocol(QSsl::TlsV1SslV3);
    request.setSslConfiguration(conf);

    QNetworkReply  *reply = manager.get(request);
    p_reply = reply;

    //绑定下载进度
    connect(reply, &QNetworkReply::downloadProgress, this, &DownloadManager::replay_progress);

#ifndef QT_NO_SSL
    connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(ssl_errors(QList<QSslError>)));
#endif
}

//保存文件数据到磁盘
bool DownloadManager::save_to_disk(const QString &filename, QIODevice *data)
{
    QFile file(filename);

    if (!file.open(QIODevice::WriteOnly)) {
        fprintf(stderr, "Could not open %s for writing: %s\n", qPrintable(filename), qPrintable(file.errorString()));
        return false;
    }

    file.write(data->readAll());
    file.close();

    return true;
}

//获取文件名称
QString DownloadManager::save_name_get(const QUrl &url)
{
    QString path = url.path();
    QString basename = QFileInfo(path).fileName();

    if (basename.isEmpty()) {
        basename = "download";
    }

    if (QFile::exists(m_path+basename)) {
        // already exists, don't overwrite
        int i = 0;
        while (QFile::exists(m_path+"("+QString::number(i)+")"+basename))
            ++i;

        basename = "("+QString::number(i)+")"+basename;
    }

    return m_path+basename;
}

//下载完毕
void DownloadManager::download_finished(QNetworkReply *reply)
{
    QUrl url = reply->url();
    if (reply->error()) {
        fprintf(stderr, "Download of %s failed: %s\n",
                url.toEncoded().constData(),
                qPrintable(reply->errorString()));
        emit download_complete(url, false, "");
    } else {

        QString filename = save_name_get(url);

        if (save_to_disk(filename, reply)) {
            printf("Download of %s succeeded (saved to %s)\n",
                   url.toEncoded().constData(),
                   qPrintable(filename));
             emit download_complete(url, true, filename);
        } else {
            emit download_complete(url, false, "");
        }
    }

    download_queue.dequeue();
    reply->deleteLater();

    p_reply = NULL;

    download();
}

void DownloadManager::ssl_errors(const QList<QSslError> &errors)
{
#ifndef QT_NO_SSL
    foreach (const QSslError &error, errors)
        fprintf(stderr, "SSL error: %s\n", qPrintable(error.errorString()));
#else
    Q_UNUSED(errors);
#endif
}

/* end file */
